package com.junjiao.util.dao;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.junjiao.util.dao.paging.QueryClass;
import com.junjiao.util.dao.paging.QueryOrderby;
import com.junjiao.util.dao.paging.QueryWhere;
import com.junjiao.util.dao.paging.QueryWhereFK;
import com.junjiao.util.dao.paging.SearchBean;
import com.junjiao.util.dao.paging.SearchResultBean;
import com.junjiao.util.java.StringUtil;

/**
 * HibernateDao操作工具类
 * 
 * @project jiaojun_util
 * @ClassName HibernateDao.java
 * @author jiaojun
 * @email junjiao.j@gmail.com
 * @version v0.0.1
 * @param <T>
 * @date 2012-4-28
 * 
 * @operate 1.使用annotation 自动注册bean,并保证@Required,@Autowired的属性被注入 <br>
 *          <context:component-scan base-package="com.junjiao.util" />
 */
public class JHibernateDao<T> {
	private Log log = LogFactory.getLog(JHibernateDao.class);

	private HibernateTemplate hibernateTemplate;

	private Session session;

	public JHibernateDao() {
	}

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		if (hibernateTemplate == null) {
			hibernateTemplate = new HibernateTemplate(sessionFactory);
		} else {
			hibernateTemplate.setSessionFactory(sessionFactory);
		}
		if (null == session) {
			session = hibernateTemplate.getSessionFactory().openSession();
		}
	}

	/**
	 * 保存新的实例
	 * 
	 * @param entity
	 * @return
	 */
	public Object save(Object entity) {
		return hibernateTemplate.save(entity);
	}

	/**
	 * 删除指定持久化实例
	 * 
	 * @param entity
	 */
	public void delete(Object entity) {
		hibernateTemplate.delete(entity);
	}

	/**
	 * 删除指定id的持久化实例
	 * 
	 * @param clz
	 *            处理的类
	 * @param id
	 */
	public void delete(Class<T> clz, Long id) {
		hibernateTemplate.delete(hibernateTemplate.get(clz, id));
	}

	/**
	 * 根据HQL查询字符串来返回实例集合
	 * 
	 * @param queryString
	 * @return 查询结果集
	 */
	public List<?> find(String queryString) {
		return hibernateTemplate.find(queryString);
	}

	/**
	 * 根据对象id查询对象
	 * 
	 * @param <T>
	 * @param clz
	 *            处理的类
	 * @param id
	 * @return 结果对象
	 */
	@SuppressWarnings("hiding")
	public <T> T find(Class<T> clz, Long id) {
		return (T) hibernateTemplate.get(clz, id);
	}

	/**
	 * 更新实例的状态，要求entity是持久状态
	 * 
	 * @param entity
	 */
	public void update(Object entity) {
		hibernateTemplate.update(entity);
	}

	/**
	 * 更新符合条件的数据
	 * 
	 * @param hql
	 *            hql语句
	 * @param params
	 *            条件参数,可空
	 * @return count 完成更新的的数据数 <br>
	 *         eg: <br>
	 *         Object[] obj = {"baidu",25663L}; <br>
	 *         update("update User u set u.name=? where id=?",obj); <br>
	 */
	public int update(String hql, Object[] params) {
		Query query = session.createQuery(hql);
		if (params != null && params.length > 0) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}
		int count = query.executeUpdate();
		hibernateTemplate.flush();
		hibernateTemplate.clear();
		return count;
	}

	/**
	 * 根据hql语句返回总记录数
	 * 
	 * @param hql
	 *            hql语句
	 * @return 总记录数 <br>
	 *         eg: <br>
	 *         Long count = count("select count(*) from User"); <br>
	 */
	public int count(String hql) {
		Query q = session.createQuery(hql);
		return Integer.valueOf(q.uniqueResult().toString());
	}

	/**
	 * 分页查询，并返回分页结果集
	 * 
	 * @param hql
	 *            查询语句
	 * @param countHql
	 *            统计总记录数语句
	 * @param searchBean
	 *            分页条件
	 * @return 返回结果集 <br>
	 *         eg: <br>
	 *         SearchBean searchBean = new SearchBean(); <br>
	 *         searchBean.setRowsPerPage(20); <br>
	 *         searchBean.setCurrentPage(1); <br>
	 *         SearchResultBean searchResultBean =
	 *         findByPaging("from User order by name desc"
	 *         ,"select count(*) from User",searchBean); <br>
	 */
	public SearchResultBean findByPaging(final String hql, String countHql,
			final SearchBean searchBean) {
		SearchResultBean searchResultBean = new SearchResultBean();
		searchResultBean.setSearchBean(searchBean);
		searchResultBean.setMaxRowCount(count(countHql));
		try {
			List<?> list = hibernateTemplate
					.executeFind(new HibernateCallback<Object>() {
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							List<?> list2 = session.createQuery(hql)
									.setFirstResult(searchBean.getStart())
									.setMaxResults(searchBean.getRowsPerPage()) // 取出10条记录
																				// **是取出10条记录
																				// 而不是取到第10条**
									.list();
							return list2;
						}
					});
			searchResultBean.setData(list);
		} catch (RuntimeException re) {
			log.error("find ListForPage failed", re);
			throw re;
		}
		return searchResultBean;

	}

	/**
	 * 多表查询
	 * 
	 * @param queryClassList
	 * @param searchBean
	 * @return
	 */
	public SearchResultBean findByPaging(List<QueryClass> queryClassList,
			SearchBean searchBean) {
		String hql = getHql(queryClassList);
		String thql = getThql(hql);
		return findByPaging(hql, thql, searchBean);
	}

	/** 获取总记录数的hql **/
	private static String getThql(String hql) {
		int index = hql.indexOf("from");
		if (index != -1) {
			return "select count(*) " + hql.substring(index);
		}
		throw new RuntimeException("无效的HQL查询语句!");
	}

	/**
	 * 
	 *摘要：通过QueryClass的列表获取一条HQL语句
	 * 
	 * @说明：
	 *@创建：作者:Qi 创建时间：Sep 8, 2009
	 *@param queryClassList
	 *            : QueryClass的列表
	 *@return
	 */
	public static String getHql(List<QueryClass> queryClassList) {
		// 类名和别名
		StringBuffer classAndOtherNameStr = new StringBuffer();

		// 查询条件
		StringBuffer queryWhereStr = new StringBuffer();

		// 查询条件外键
		StringBuffer queryWhereFKStr = new StringBuffer();

		// orderby
		StringBuffer orderbyStr = new StringBuffer();

		for (int i = 0; i < queryClassList.size(); i++) {
			QueryClass queryClass = queryClassList.get(i);

			// className otherName
			classAndOtherNameStr.append(queryClass.getClassAndOtherNameStr())
					.append(" ");
			if (i != queryClassList.size() - 1)
				classAndOtherNameStr.append(",");

			// 查询条件参数
			List<QueryWhere> queryWhereList = queryClass.getQueryWhereList();
			for (int j = 0; j < queryWhereList.size(); j++) {
				QueryWhere queryWhere = queryWhereList.get(j);
				if (!StringUtil.isNull(queryWhere.getPropertyValue())) {// 如果值不为空的话
					queryWhereStr.append(
							queryWhere.getQueryWhereStr(queryClass
									.getOtherName())).append(" ");
				}
			}

			// 查询条件外键
			List<QueryWhere> queryWhereFKList = queryClass
					.getQueryWhereFKList();
			for (int c = 0; c < queryWhereFKList.size(); c++) {
				QueryWhereFK queryWhereFK = (QueryWhereFK) queryWhereFKList
						.get(c);
				if (!StringUtil.isNull(queryWhereFK.getPropertyValue())) {// 如果值不为空的话
					queryWhereFKStr.append(queryWhereFK.getQueryWhereFKStr())
							.append(" ");
				}
			}

			// orderby
			List<QueryOrderby> queryOrderbyList = queryClass
					.getQueryOrderbyList();
			for (int k = 0; k < queryOrderbyList.size(); k++) {
				QueryOrderby queryOrder = queryOrderbyList.get(k);
				if (!StringUtil.isNull(queryOrder.getAscOrDesc())) {// 如果值不为空的话
					if (!orderbyStr.toString().startsWith("order by"))
						orderbyStr.append("order by").append(" ");
					if (!queryOrder.isOrderByPinyin()) {
						orderbyStr.append(
								queryOrder.getQueryOrderbyStr(queryClass
										.getOtherName())).append(",");
					} else {
						orderbyStr.append(
								queryOrder.getPinyinQueryOrderbyStr(queryClass
										.getOtherName())).append(",");
					}
				}
			}
		}

		String tempOrderbyStr = "";// 临时存放orderby的str
		if (orderbyStr.length() > 0) {// 去掉orderby的最后一个逗号
			tempOrderbyStr = orderbyStr.substring(0, orderbyStr.length() - 1);
		}

		// hql
		StringBuffer hql = new StringBuffer("from ");
		hql.append(classAndOtherNameStr).append("where 1=1 ").append(
				queryWhereStr).append(queryWhereFKStr).append(tempOrderbyStr);
		return hql.toString();
	}
	/*
	 * Configuration config = new Configuration(); SessionFactory sessionFactory
	 * = config.configure().buildSessionFactory();
	 * 
	 * Criteria criteria = session.createCriteria(MyPoJo.class);
	 * 
	 * //等于条件 //Restrictions.eq(String,object);
	 * criteria.add(Restrictions.eq("UserID", 1001));
	 * 
	 * //其它条件以此类推 Restrictions.gt 对应SQL中的 “field > value ” 表达式 Restrictions.ge
	 * 对应SQL中的 “field >= value” 表达式 Restrictions.lt 对应SQL中的 “field < value” 表达式
	 * Restrictions.le 对应SQL中的 “field <= value” 表达式 Restrictions.between 对应SQL中的
	 * “between” 表达式 Restrictions.in 传入一个数组进行IN查询 Restrictions.like 进行模糊查询
	 * Restrictions.ilike 不区分大小写的模糊查询
	 */
}
